import 'package:flutter/material.dart';

void main() => runApp(MyApp());

// 更精确的监听手势，Listener组件
class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
          appBar: AppBar(
            title: Text('触摸事件监听'),
          ),
          body:
              //GestureWidget() // 手势识别
              NestWidget()
          // ListenerWidget(), // 触摸监听
          ),
    );
  }
}

// 不同于button，大多数控件不带点击事件这时候就需要GestureDetector手势监听，GestureDetector也是一个Widget
// 也可以使用InkWell实现水波纹效果,用法相同
class GestureWidget extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return SingleChildScrollView(
      child: Column(
        children: [
          // 点击手势监听
          GestureDetector(
            child: Container(
              width: double.infinity,
              height: 100.0,
              color: Colors.redAccent,
            ),
            onTap: () {
              debugPrint('点击');
            },
            onDoubleTap: () => debugPrint('双击'),
            onLongPress: () => debugPrint('长按'),
          ),
          // 滑动手势监听
          GestureDetector(
            child: Container(
              width: double.infinity,
              height: 100.0,
              color: Colors.yellow,
            ),
            onPanDown: (details) =>
                debugPrint('手势滑动按下：${details.globalPosition}'),
            onPanUpdate: (details) =>
                debugPrint('手势滑动中：${details..delta.dx}--${details.delta.dy}'),
            onPanEnd: (details) =>
                debugPrint('手势滑动结束，瞬时速度：${details.velocity.pixelsPerSecond}'),
            /* onTap: () {
              debugPrint('点击');
            },
            onDoubleTap: () => debugPrint('双击'),
            onLongPress: () => debugPrint('长按'),*/
          ),

          // 上述中onPanDown、onTap共存时，有可能只有onPanDown执行
          // flutter为了解决复杂手势问题引入竞技者概念，在竞争中onPanDown获胜了只有它里面的内容执行
          // 对于只想获取某个方向的平移(垂直、水平)这也是竞争，如果要忽略某个方向，只留一个方向
          GestureDetector(
            child: Container(
              width: double.infinity,
              height: 100.0,
              color: Colors.yellow,
            ),
            onHorizontalDragDown: (details) =>
                debugPrint('手势滑动按下：${details.globalPosition}'),
            onHorizontalDragUpdate: (details) =>
                debugPrint('手势滑动中：${details..delta.dx}--${details.delta.dy}'),
            onHorizontalDragEnd: (details) =>
                debugPrint('手势滑动结束，瞬时速度：${details.velocity.pixelsPerSecond}'),
          ),
        ],
      ),
    );
  }
}

// Container嵌套小Container，要求点击小Container不传递到大的Container(偶尔会出现事件传递)
// 解决方式使用Stack包裹两个Container，让两者互补嵌套
class NestWidget extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Center(
      child: GestureDetector(
        onTapDown: (detail) => print('outter down'),
        child: Container(
          color: Colors.red,
          width: 100,
          height: 100,
          // 有固定宽高的Container嵌套Container会有tight的约束，内层Container扩展到外层的宽高
          // 使用alignment属性，会为内层Container嵌套一个Align，解决该问题
          alignment: Alignment.center,
          child: GestureDetector(
            onTapDown: (detail) => print('inner down'),
            child: Container(
              width: 50,
              height: 50,
              color: Colors.yellow,
            ),
          ),
        ),
      ),
    );
  }
}

// 指针事件：人机交互的原始事件
class ListenerWidget extends StatelessWidget {
  const ListenerWidget({
    Key key,
  }) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return SingleChildScrollView(
      child: Column(
        children: [
          Listener(
            child: Container(
              width: double.infinity,
              height: 200.0,
              color: Colors.yellow,
            ),
            // position相对于屏幕,localPosition表示点击该控件的坐标
            onPointerDown: (event) => debugPrint(
                "onPointerDown==${event.pointer}:${event.localPosition}"),
            onPointerUp: (event) => debugPrint("onPointerUp==$event"),
            onPointerMove: (event) => debugPrint("onPointerMove==$event"),
          ),
          Listener(
            // 当希望某个组件不相应事件可使用IgnorePointer、AbsorbPointer包裹
            child: IgnorePointer(
              child: Container(
                width: double.infinity,
                height: 200.0,
                color: Colors.blue,
              ),
            ),
            onPointerDown: (event) => debugPrint("onPointerDown==$event"),
            onPointerUp: (event) => debugPrint("onPointerUp==$event"),
            onPointerMove: (event) => debugPrint("onPointerMove==$event"),
          ),
          Listener(
            child: Container(
              width: double.infinity,
              height: 200.0,
              color: Colors.redAccent,
            ),
            onPointerDown: (event) => debugPrint("onPointerDown==$event"),
            onPointerUp: (event) => debugPrint("onPointerUp==$event"),
            onPointerMove: (event) => debugPrint("onPointerMove==$event"),
            // 多个组件叠加，触摸事件的响应方式
            // deferToChild 依次想下传递
            // opaque 强制让控件不透明，让后面的控件不能响应事件
            // translucent 让控件透明(透明控件不响应事件) 使事件向后传递
            behavior: HitTestBehavior.translucent,
          ),
        ],
      ),
    );
  }
}
